#pragma once
#include "log.hpp"
#include "config.hpp"
#include <unordered_map>
#include <pthread.h>
#include <vector>
namespace cloud
{
    typedef struct Backupinfo_t
    {
        bool _pack_flag;//文件是否压缩标志
        size_t _fsize;//文件大小
        time_t _atime;//文件最后访问时间
        time_t _mtime;//文件最后修改时间
        std::string _real_path;//文件实际存储路径名称
        std::string _pack_path;//压缩包存储路径名称
        std::string _url_path;
        void NewBackupinfo(std::string real_path)//你给我传入一个文件真实路径，我返回给你一个填充好关于这个文件各项属性的结构体
        {
            cloud::FileUtil fu(real_path);
            cloud::Config* conf = cloud::Config::Getinstance();//从单例模式中拿到操作句柄
            _pack_flag = 0;
            _fsize = fu.FileSize();
            _atime = fu.LastATime();
            _mtime = fu.LastMTime();
            _real_path = real_path;
            std::string packdir = conf->Get_pack_dir();
            std::string fname = fu.FileName();
            std::string packsuffix = conf->Get_packfile_suffix();
            _pack_path = packdir + fname + packsuffix;
            std::string urlpath = conf->Get_download_prefix();
            _url_path = urlpath + fname;
        }
    }Backupinfo;

    class DataManager
    {
    public:
        DataManager()
        {
            pthread_rwlock_init(&_rwlock,nullptr);//初始化读写锁
            cloud::Config* conf = cloud::Config::Getinstance();
            _backup_file = conf->Get_backup_file();//获取持久化存储文件路径，说白了就是把已经存下来的文件保存下来，以后再重启系统能接着用
            InitLoad();
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock);//销毁读写锁
        }
        bool Storage()//每次数据新增或修改都要更改持久化存储，避免数据丢失
        {
            //获取所有文件
            //std::unordered_map<std::string,Backupinfo> _table;//在内存中以hash表存储
            Json::Value root;
            for(auto& iter:_table)
            {
                Json::Value item;
                item["_pack_flag"] = iter.second._pack_flag;
                item["_fsize"] = iter.second._fsize;
                item["_atime"] = iter.second._atime;
                item["_mtime"] = iter.second._mtime;
                item["_pack_path"] = iter.second._pack_path;
                item["_real_path"] = iter.second._real_path;
                item["_url_path"] = iter.second._url_path;
                root.append(item);
            }
            //序列化
            std::string body;
            cloud::JsonUtil::Serialize(root,&body);
            //写文件
            cloud::FileUtil fu(_backup_file);
            if(fu.SetContent(&body) == false)
            {
                logMassage(ERROR,"持久化数据时写入文件错误！\n");
                return false;
            }
            return true;
        }
        bool InitLoad()//初始化加载，每次系统重启都要讲持久化存储中的文件读取到内存中
        {
            cloud::FileUtil fu(_backup_file);
            if(fu.Exists() == false) return true;
            //走到这说明配置文件存在
            if(fu.FileSize() == 0) return true;
            //走到这说明配置文件存在且大小不为0
            std::string body;
            fu.GetContent(&body);//将文件中的内容读取到body中
            //std::cout<<body<<std::endl;
            Json::Value root;
            memset(&root,0,sizeof(root));
            cloud::JsonUtil::DeSerialize(body,&root);//将反序列化后的内容存入root
            //接下来要把value的内容存进_table中
            for(auto iter:root)
            {
                cloud::Backupinfo bi;
                bi._pack_flag = iter["_pack_flag"].asBool();
                bi._fsize = iter["_fsize"].asUInt64();
                bi._atime = iter["_atime"].asInt64();
                bi._mtime = iter["_mtime"].asInt64();
                bi._pack_path = iter["_pack_path"].asString();
                bi._real_path = iter["_real_path"].asString();
                bi._url_path = iter["_url_path"].asString();
                if(insert(bi) == false)
                {
                    logMassage(ERROR,"系统初始化失败！\n");
                    return false;
                }
            }
            return true;
        }
        bool insert(const Backupinfo& bi)//新增
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[bi._url_path] = bi;
            pthread_rwlock_unlock(&_rwlock);
            if(Storage() == false)
            {
                return false;
            }
            return true;
        }
        bool Update(const Backupinfo& bi)//修改
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[bi._url_path] = bi;
            pthread_rwlock_unlock(&_rwlock);
            if(Storage() == false)
            {
                return false;
            }
            return true;
        }
        bool GetOneByurl(const std::string& url,Backupinfo* bi)//获取一个url 传入一个string 输出型参数Backupinfo
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto iter = _table.find(url);//查找key值
            if(iter == _table.end())
            {
                //logMassage(ERROR,"你要查找的文件不存在！\n");
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            *bi = iter->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealpath(const std::string& path,Backupinfo* bi)//获取一个url 传入一个string 输出型参数Backupinfo
        {
            pthread_rwlock_wrlock(&_rwlock);
            for(auto iter:_table)
            {
                if(iter.second._real_path == path)
                {
                    *bi = iter.second;
                    pthread_rwlock_unlock(&_rwlock);
                    return true;
                }
            }
            //logMassage(ERROR,"你要查找的文件不存在！\n");
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        bool GetAll(std::vector<Backupinfo>* arr)//获取所有备份文件信息
        {
            pthread_rwlock_wrlock(&_rwlock);
            for(auto iter:_table)
            {
                arr->push_back(iter.second);
            }
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
    private:
        std::string _backup_file;//持久化存储文件
        std::unordered_map<std::string,Backupinfo> _table;//在内存中以hash表存储
        pthread_rwlock_t _rwlock;//读写锁，读共享，写互斥
    };
}